<!DOCTYPE html>
<html>

<head>
    <title>Threejs中使用A*算法寻路导航，Threejs室内室外地图导航</title>
    <script type="text/javascript" src="libs/three.js"></script>
    <script type="text/javascript" src="libs/OrbitControls.js"></script>
    <script type="text/javascript" charset="UTF-8" src="libs/other/Tween.min.js"></script>
    <script type="text/javascript" charset="UTF-8" src="libs/three/loaders/GLTFLoader.js"></script>

    <script type="text/javascript" src="libs/OBJLoader.js"></script>
    <script type="text/javascript" src="libs/MTLLoader.js"></script>

    <script type="text/javascript" src="libs/util.js"></script>
    <script type="text/javascript" src="libs/util/dat.gui.js"></script>
    <script type="text/javascript" src="libs/astar.js"></script>
    <style>
        body {
            margin: 0;
            overflow: hidden;
        }
    </style>
</head>

<body>
    <div id="webgl-output"></div>
    <script type="text/javascript">
        var camera;
        var renderer;
        var clock = new THREE.Clock();
        var mixer = new THREE.AnimationMixer();
        var clipAction;
        var animationClip;
        var length = 36;
        var ws = 2;
        var graph = []; // 记录地图
        var meshArr = new Array(); // 记录障碍物对象数据
        var meshxy = [{
            "x": 35,
            "y": 7
        },
        {
            "x": 35,
            "y": 7
        },
        {
            "x": 35,
            "y": 9
        },
        {
            "x": 35,
            "y": 11
        },
        {
            "x": 29,
            "y": 11
        },
        {
            "x": 29,
            "y": 13
        },
        {
            "x": 33,
            "y": 13
        },
        {
            "x": 33,
            "y": 11
        },
        {
            "x": 33,
            "y": 9
        },
        {
            "x": 33,
            "y": 5
        },
        {
            "x": 33,
            "y": 7
        },
        {
            "x": 29,
            "y": 5
        },
        {
            "x": 31,
            "y": 5
        },
        {
            "x": 31,
            "y": 11
        },
        {
            "x": 27,
            "y": 5
        },
        {
            "x": 25,
            "y": 5
        },
        {
            "x": 25,
            "y": 7
        },
        {
            "x": 25,
            "y": 9
        },
        {
            "x": 25,
            "y": 11
        },
        {
            "x": 25,
            "y": 13
        },
        {
            "x": 23,
            "y": 9
        },
        {
            "x": 21,
            "y": 9
        },
        {
            "x": 19,
            "y": 9
        },
        {
            "x": 19,
            "y": 11
        },
        {
            "x": 19,
            "y": 13
        },
        {
            "x": 15,
            "y": 9
        },
        {
            "x": 13,
            "y": 7
        },
        {
            "x": 13,
            "y": 9
        },
        {
            "x": 13,
            "y": 11
        },
        {
            "x": 11,
            "y": 7
        },
        {
            "x": 13,
            "y": 5
        },
        {
            "x": 11,
            "y": 5
        },
        {
            "x": 7,
            "y": 5
        },
        {
            "x": 5,
            "y": 5
        },
        {
            "x": 5,
            "y": 7
        },
        {
            "x": 7,
            "y": 7
        },
        {
            "x": 7,
            "y": 9
        },
        {
            "x": 7,
            "y": 11
        },
        {
            "x": 5,
            "y": 11
        },
        {
            "x": 5,
            "y": 9
        },
        {
            "x": 7,
            "y": 15
        },
        {
            "x": 7,
            "y": 17
        },
        {
            "x": 7,
            "y": 19
        },
        {
            "x": 11,
            "y": 23
        },
        {
            "x": 11,
            "y": 17
        },
        {
            "x": 11,
            "y": 21
        },
        {
            "x": 11,
            "y": 19
        },
        {
            "x": 17,
            "y": 25
        },
        {
            "x": 17,
            "y": 27
        },
        {
            "x": 17,
            "y": 29
        },
        {
            "x": 19,
            "y": 25
        },
        {
            "x": 21,
            "y": 25
        },
        {
            "x": 17,
            "y": 21
        },
        {
            "x": 17,
            "y": 23
        },
        {
            "x": 17,
            "y": 19
        },
        {
            "x": 15,
            "y": 19
        },
        {
            "x": 13,
            "y": 19
        },
        {
            "x": 7,
            "y": 29
        },
        {
            "x": 7,
            "y": 31
        },
        {
            "x": 7,
            "y": 33
        },
        {
            "x": 9,
            "y": 33
        },
        {
            "x": 13,
            "y": 33
        },
        {
            "x": 11,
            "y": 33
        },
        {
            "x": 13,
            "y": 31
        },
        {
            "x": 13,
            "y": 29
        },
        {
            "x": 15,
            "y": 33
        },
        {
            "x": 17,
            "y": 33
        },
        {
            "x": 19,
            "y": 33
        },
        {
            "x": 21,
            "y": 33
        },
        {
            "x": 25,
            "y": 29
        },
        {
            "x": 25,
            "y": 31
        },
        {
            "x": 25,
            "y": 33
        },
        {
            "x": 27,
            "y": 29
        },
        {
            "x": 29,
            "y": 29
        },
        {
            "x": 29,
            "y": 23
        },
        {
            "x": 27,
            "y": 23
        },
        {
            "x": 25,
            "y": 23
        },
        {
            "x": 29,
            "y": 21
        },
        {
            "x": 29,
            "y": 19
        },
        {
            "x": 33,
            "y": 19
        },
        {
            "x": 33,
            "y": 21
        },
        {
            "x": 33,
            "y": 23
        },
        {
            "x": 33,
            "y": 25
        },
        {
            "x": 33,
            "y": 27
        },
        {
            "x": 33,
            "y": 29
        },
        {
            "x": 33,
            "y": 31
        },
        {
            "x": 33,
            "y": 33
        },
        {
            "x": 31,
            "y": 35
        },
        {
            "x": 29,
            "y": 35
        },
        {
            "x": 27,
            "y": 35
        },
        {
            "x": 25,
            "y": 35
        },
        {
            "x": 7,
            "y": 23
        },
        {
            "x": 11,
            "y": 15
        },
        {
            "x": 9,
            "y": 15
        },
        {
            "x": 35,
            "y": 9
        },
        {
            "x": 35,
            "y": 11
        },
        {
            "x": 29,
            "y": 11
        },
        {
            "x": 29,
            "y": 13
        },
        {
            "x": 33,
            "y": 13
        },
        {
            "x": 33,
            "y": 11
        },
        {
            "x": 33,
            "y": 9
        },
        {
            "x": 33,
            "y": 5
        },
        {
            "x": 33,
            "y": 7
        },
        {
            "x": 29,
            "y": 5
        },
        {
            "x": 31,
            "y": 5
        },
        {
            "x": 31,
            "y": 11
        },
        {
            "x": 27,
            "y": 5
        },
        {
            "x": 25,
            "y": 5
        },
        {
            "x": 25,
            "y": 7
        },
        {
            "x": 25,
            "y": 9
        },
        {
            "x": 25,
            "y": 11
        },
        {
            "x": 25,
            "y": 13
        },
        {
            "x": 23,
            "y": 9
        },
        {
            "x": 21,
            "y": 9
        },
        {
            "x": 19,
            "y": 9
        },
        {
            "x": 19,
            "y": 11
        },
        {
            "x": 19,
            "y": 13
        },
        {
            "x": 15,
            "y": 9
        },
        {
            "x": 13,
            "y": 7
        },
        {
            "x": 13,
            "y": 9
        },
        {
            "x": 13,
            "y": 11
        },
        {
            "x": 11,
            "y": 7
        },
        {
            "x": 13,
            "y": 5
        },
        {
            "x": 11,
            "y": 5
        },
        {
            "x": 7,
            "y": 5
        },
        {
            "x": 5,
            "y": 5
        },
        {
            "x": 5,
            "y": 7
        },
        {
            "x": 7,
            "y": 7
        },
        {
            "x": 7,
            "y": 9
        },
        {
            "x": 7,
            "y": 11
        },
        {
            "x": 5,
            "y": 11
        },
        {
            "x": 5,
            "y": 9
        },
        {
            "x": 7,
            "y": 15
        },
        {
            "x": 7,
            "y": 17
        },
        {
            "x": 7,
            "y": 19
        },
        {
            "x": 11,
            "y": 23
        },
        {
            "x": 11,
            "y": 17
        },
        {
            "x": 11,
            "y": 21
        },
        {
            "x": 11,
            "y": 19
        },
        {
            "x": 17,
            "y": 25
        },
        {
            "x": 17,
            "y": 27
        },
        {
            "x": 17,
            "y": 29
        },
        {
            "x": 19,
            "y": 25
        },
        {
            "x": 21,
            "y": 25
        },
        {
            "x": 17,
            "y": 21
        },
        {
            "x": 17,
            "y": 23
        },
        {
            "x": 17,
            "y": 19
        },
        {
            "x": 15,
            "y": 19
        },
        {
            "x": 13,
            "y": 19
        },
        {
            "x": 7,
            "y": 29
        },
        {
            "x": 7,
            "y": 31
        },
        {
            "x": 7,
            "y": 33
        },
        {
            "x": 9,
            "y": 33
        },
        {
            "x": 13,
            "y": 33
        },
        {
            "x": 11,
            "y": 33
        },
        {
            "x": 13,
            "y": 31
        },
        {
            "x": 13,
            "y": 29
        },
        {
            "x": 15,
            "y": 33
        },
        {
            "x": 17,
            "y": 33
        },
        {
            "x": 19,
            "y": 33
        },
        {
            "x": 21,
            "y": 33
        },
        {
            "x": 25,
            "y": 29
        },
        {
            "x": 25,
            "y": 31
        },
        {
            "x": 25,
            "y": 33
        },
        {
            "x": 27,
            "y": 29
        },
        {
            "x": 29,
            "y": 29
        },
        {
            "x": 29,
            "y": 23
        },
        {
            "x": 27,
            "y": 23
        },
        {
            "x": 25,
            "y": 23
        },
        {
            "x": 29,
            "y": 21
        },
        {
            "x": 29,
            "y": 19
        },
        {
            "x": 33,
            "y": 19
        },
        {
            "x": 33,
            "y": 21
        },
        {
            "x": 33,
            "y": 23
        },
        {
            "x": 33,
            "y": 25
        },
        {
            "x": 33,
            "y": 27
        },
        {
            "x": 33,
            "y": 29
        },
        {
            "x": 33,
            "y": 31
        },
        {
            "x": 33,
            "y": 33
        },
        {
            "x": 31,
            "y": 35
        },
        {
            "x": 29,
            "y": 35
        },
        {
            "x": 27,
            "y": 35
        },
        {
            "x": 25,
            "y": 35
        },
        {
            "x": 7,
            "y": 23
        },
        {
            "x": 11,
            "y": 15
        },
        {
            "x": 9,
            "y": 15
        },
        {
            "x": 35,
            "y": 9
        },
        {
            "x": 35,
            "y": 11
        },
        {
            "x": 29,
            "y": 11
        },
        {
            "x": 29,
            "y": 13
        },
        {
            "x": 33,
            "y": 13
        },
        {
            "x": 33,
            "y": 11
        },
        {
            "x": 33,
            "y": 9
        },
        {
            "x": 33,
            "y": 5
        },
        {
            "x": 33,
            "y": 7
        },
        {
            "x": 29,
            "y": 5
        },
        {
            "x": 31,
            "y": 5
        },
        {
            "x": 31,
            "y": 11
        },
        {
            "x": 27,
            "y": 5
        },
        {
            "x": 25,
            "y": 5
        },
        {
            "x": 25,
            "y": 7
        },
        {
            "x": 25,
            "y": 9
        },
        {
            "x": 25,
            "y": 11
        },
        {
            "x": 25,
            "y": 13
        },
        {
            "x": 23,
            "y": 9
        },
        {
            "x": 21,
            "y": 9
        },
        {
            "x": 19,
            "y": 9
        },
        {
            "x": 19,
            "y": 11
        },
        {
            "x": 19,
            "y": 13
        },
        {
            "x": 15,
            "y": 9
        },
        {
            "x": 13,
            "y": 7
        },
        {
            "x": 13,
            "y": 9
        },
        {
            "x": 13,
            "y": 11
        },
        {
            "x": 11,
            "y": 7
        },
        {
            "x": 13,
            "y": 5
        },
        {
            "x": 11,
            "y": 5
        },
        {
            "x": 7,
            "y": 5
        },
        {
            "x": 5,
            "y": 5
        },
        {
            "x": 5,
            "y": 7
        },
        {
            "x": 7,
            "y": 7
        },
        {
            "x": 7,
            "y": 9
        },
        {
            "x": 7,
            "y": 11
        },
        {
            "x": 5,
            "y": 11
        },
        {
            "x": 5,
            "y": 9
        },
        {
            "x": 7,
            "y": 15
        },
        {
            "x": 7,
            "y": 17
        },
        {
            "x": 7,
            "y": 19
        },
        {
            "x": 11,
            "y": 23
        },
        {
            "x": 11,
            "y": 17
        },
        {
            "x": 11,
            "y": 21
        },
        {
            "x": 11,
            "y": 19
        },
        {
            "x": 17,
            "y": 25
        },
        {
            "x": 17,
            "y": 27
        },
        {
            "x": 17,
            "y": 29
        },
        {
            "x": 19,
            "y": 25
        },
        {
            "x": 21,
            "y": 25
        },
        {
            "x": 17,
            "y": 21
        },
        {
            "x": 17,
            "y": 23
        },
        {
            "x": 17,
            "y": 19
        },
        {
            "x": 15,
            "y": 19
        },
        {
            "x": 13,
            "y": 19
        },
        {
            "x": 7,
            "y": 29
        },
        {
            "x": 7,
            "y": 31
        },
        {
            "x": 7,
            "y": 33
        },
        {
            "x": 9,
            "y": 33
        },
        {
            "x": 13,
            "y": 33
        },
        {
            "x": 11,
            "y": 33
        },
        {
            "x": 13,
            "y": 31
        },
        {
            "x": 13,
            "y": 29
        },
        {
            "x": 15,
            "y": 33
        },
        {
            "x": 17,
            "y": 33
        },
        {
            "x": 19,
            "y": 33
        },
        {
            "x": 21,
            "y": 33
        },
        {
            "x": 25,
            "y": 29
        },
        {
            "x": 25,
            "y": 31
        },
        {
            "x": 25,
            "y": 33
        },
        {
            "x": 27,
            "y": 29
        },
        {
            "x": 29,
            "y": 29
        },
        {
            "x": 29,
            "y": 23
        },
        {
            "x": 27,
            "y": 23
        },
        {
            "x": 25,
            "y": 23
        },
        {
            "x": 29,
            "y": 21
        },
        {
            "x": 29,
            "y": 19
        },
        {
            "x": 33,
            "y": 19
        },
        {
            "x": 33,
            "y": 21
        },
        {
            "x": 33,
            "y": 23
        },
        {
            "x": 33,
            "y": 25
        },
        {
            "x": 33,
            "y": 27
        },
        {
            "x": 33,
            "y": 29
        },
        {
            "x": 33,
            "y": 31
        },
        {
            "x": 33,
            "y": 33
        },
        {
            "x": 31,
            "y": 35
        },
        {
            "x": 29,
            "y": 35
        },
        {
            "x": 27,
            "y": 35
        },
        {
            "x": 25,
            "y": 35
        },
        {
            "x": 7,
            "y": 23
        },
        {
            "x": 11,
            "y": 15
        },
        {
            "x": 9,
            "y": 15
        },
        {
            "x": 19,
            "y": 21
        },
        {
            "x": 21,
            "y": 21
        },
        {
            "x": 21,
            "y": 19
        },
        {
            "x": 29,
            "y": 27
        },
        {
            "x": 29,
            "y": 25
        }
        ]; // 记录障碍坐标物数据
        var lineArr = new Array(); // 记录路网数据
        var meshbool = false; // 显示障碍物
        var linebool = false; // 显示路网
        var resultArray = new Array();
        var isCaculate = false;

        function init() {
            // 创建一个场景，它将包含我们所有的元素，如物体，相机和灯光。
            var scene = new THREE.Scene();

            var urls = [
                'assets/textures/cubemap/flowers/posx.jpg',
                'assets/textures/cubemap/flowers/negx.jpg',
                'assets/textures/cubemap/flowers/posy.jpg',
                'assets/textures/cubemap/flowers/negy.jpg',
                'assets/textures/cubemap/flowers/posz.jpg',
                'assets/textures/cubemap/flowers/negz.jpg'
            ];

            var cubeLoader = new THREE.CubeTextureLoader();
            scene.background = cubeLoader.load(urls);

            // 创建一个摄像机，它定义了我们正在看的地方
            camera = new THREE.PerspectiveCamera(40, window.innerWidth / window.innerHeight, 0.1, 1000);
            // 将摄像机对准场景的中心
            camera.position.x = 60;
            camera.position.y = 35;
            camera.position.z = 60;
            camera.lookAt({
                x: 0,
                y: 5,
                z: -20
            });
            var orbit = new THREE.OrbitControls(camera);
            orbit.target = camera.position;
            orbit.update();

            // 创建一个渲染器并设置大小，WebGLRenderer将会使用电脑显卡来渲染场景
            // initialize basic renderer
            renderer = initRenderer({
                antialias: true,
                logarithmicDepthBuffer: true,
            });

            // 将平面添加到场景中
            var plane = createPlaneGeometryBasicMaterial();
            scene.add(plane);

            // 在屏幕上显示坐标轴
            var axes = new THREE.AxesHelper(100);
            scene.add(axes);

            scene.add(new THREE.AmbientLight(0x666666));
            scene.add(new THREE.AmbientLight("#ffffff", 1));

            initModel();
            // initPeople();

            initGround();
            initGrid();

            var i = 0;

            function tweenComplete() {
                if (i < points.length) {
                    switch (i) {
                        case 0:
                            aaa.rotateY(Math.PI);
                            break;
                        case 1:
                        case 5:
                        case 8:
                        case 9:
                            aaa.rotateY(-0.5 * Math.PI);
                            break;
                        case 2:
                        case 3:
                        case 4:
                        case 6:
                        case 7:
                            aaa.rotateY(0.5 * Math.PI);
                            break;
                        case 10:
                            mixer.stopAllAction();
                            break;

                    }
                    tween = new TWEEN.Tween(points[i])
                        .to(points[i + 1], 3000)
                        .easing(TWEEN.Easing.Linear.None)
                        .onUpdate(function () {
                            aaa.position.set(this.x, this.y, this.z);
                        })
                        .onComplete(tweenComplete)
                        .start();
                    i++;
                }
            }


            // 使用GUI调试库
            var controls = new function () {
                this.clickBool = false;

                this.displayRoadGrid = function () {
                    for (var i = 0; i < lineArr.length; i++) {
                        if (linebool) {
                            // 显示路网
                            scene.add(lineArr[i].obj);
                        } else {
                            // 隐藏路网
                            var obj = scene.getObjectByName(lineArr[i].name);
                            scene.remove(obj);
                        }
                    }
                    linebool = !linebool
                }

                this.displayObstacles = function () {
                    for (var i = 0; i < meshArr.length; i++) {
                        if (meshbool) {
                            // 显示障碍物
                            scene.add(meshArr[i].obj);
                        } else {
                            // 隐藏障碍物
                            var obj = scene.getObjectByName(meshArr[i].name);
                            scene.remove(obj);
                        }
                    }
                    meshbool = !meshbool
                }

                this.outputObstacles = function () {
                    for (var i = 0; i < meshArr.length; i++) {
                        meshxy.push({
                            x: meshArr[i].x,
                            y: meshArr[i].y
                        })
                    }
                    console.log(meshArr)
                    console.log(lineArr)
                    console.log(meshxy)
                    localStorage.setItem('meshArr', JSON.stringify(meshArr));
                    localStorage.setItem('lineArr', JSON.stringify(lineArr));
                    localStorage.setItem('meshxy', JSON.stringify(meshxy));
                }
            }
            var gui = new dat.GUI();
            // 隐藏显示障路网
            gui.add(controls, 'displayRoadGrid');
            // 隐藏显示障碍物
            gui.add(controls, 'displayObstacles');
            // 输出障碍物对象
            gui.add(controls, 'outputObstacles');
            gui.add(controls, "clickBool");

            // 启动动画
            renderScene();

            // 添加模型
            function initModel() {
                var mtlLoader = new THREE.MTLLoader();
                mtlLoader.setPath("assets/models/obj_mtl/")
                mtlLoader.load('city.mtl', function (materials) {
                    materials.preload();

                    var objLoader = new THREE.OBJLoader();
                    objLoader.setMaterials(materials);
                    objLoader.load('assets/models/obj_mtl/city.obj', function (object) {
                        var mesh = object;
                        mesh.scale.set(3, 3, 3);
                        mesh.position.set(18, 0, 18);
                        scene.add(mesh);
                    });
                });
            }

            // 添加人物模型
            function initPeople() {
                var loader = new THREE.GLTFLoader();
                loader.load('assets/models/CesiumMan/CesiumMan.gltf', function (result) {
                    result.scene.scale.set(1, 1, 1);
                    result.scene.translateY(0);
                    aaa = result.scene;
                    scene.add(result.scene);

                    tweenComplete();

                    mixer = new THREE.AnimationMixer(result.scene);
                    animationClip = result.animations[0];
                    clipAction = mixer.clipAction(animationClip).play();
                    animationClip = clipAction.getClip();
                });
            }

            // 创建一个地面并设置草坪材质
            function createPlaneGeometryBasicMaterial() {
                var textureLoader = new THREE.TextureLoader();
                var cubeMaterial = new THREE.MeshStandardMaterial({
                    map: textureLoader.load("assets/textures/stone/cd.jpg"),
                });
                cubeMaterial.map.wrapS = THREE.RepeatWrapping;
                cubeMaterial.map.wrapT = THREE.RepeatWrapping;
                cubeMaterial.map.repeat.set(18, 18)
                // 创建地平面并设置大小
                var planeGeometry = new THREE.PlaneGeometry(500, 500);
                var plane = new THREE.Mesh(planeGeometry, cubeMaterial);

                // 设置平面位置并旋转
                plane.rotation.x = -0.5 * Math.PI;
                plane.position.x = 0;
                plane.position.z = 0;
                return plane;
            }

            // 绘制线路
            function initLine(pArr) {
                var points = [];
                var geometry = new THREE.Geometry();
                for (var i = 0; i < pArr.length; i++) {
                    var randomX = pArr[i].x;
                    var randomY = pArr[i].y;
                    var randomZ = pArr[i].z;
                    var vector = new THREE.Vector3(randomX, randomY, randomZ);
                    geometry.vertices.push(vector);
                    points.push(vector);
                }
                var material = new THREE.LineBasicMaterial({
                    color: 0x0000FF
                });
                var line = new THREE.Line(geometry, material);
                scene.add(line);
                return points;
            }

            // 绘制路网
            function initGround() {
                var geometry = new THREE.Geometry();
                geometry.vertices.push(new THREE.Vector3(0, 0, 0));
                geometry.vertices.push(new THREE.Vector3(length, 0, 0));

                for (var i = 0; i <= length / ws; i++) {
                    var material = new THREE.LineBasicMaterial({
                        color: 0x808080
                    });
                    var line = new THREE.Line(geometry, material);
                    line.position.z = i * ws;
                    line.name = "line_" + i;
                    lineArr.push({
                        name: "line_" + i,
                        obj: line
                    });
                    scene.add(line);

                    var line = new THREE.Line(geometry, material);
                    line.position.x = i * ws;
                    line.position.z = length;
                    line.rotation.y = 90 * Math.PI / 180;
                    line.name = "line_" + i + 180;
                    lineArr.push({
                        name: "line_" + i + 180,
                        obj: line
                    });
                    scene.add(line);
                }
            }

            // 初始化障碍物随机
            function initGrid() {
                for (var i = 0; i < length / ws; i++) {
                    var nodeRow = [];
                    for (var j = 0; j < length / ws; j++) {
                        nodeRow.push(1);
                    }
                    graph.push(nodeRow);
                }
                if (meshxy.length > 0) {
                    for (var i = 0; i < meshxy.length; i++) {
                        initObstacles(meshxy[i].x, meshxy[i].y);
                    }
                } else {
                    for (var i = 0; i < length / ws; i++) {
                        var nodeRow = [];
                        for (var j = 0; j < length / ws; j++) {
                            var salt = Math.random() * 7;
                            if (salt > 2) {
                                nodeRow.push(1);
                            } else {
                                nodeRow.push(0);
                            }
                            if (salt <= 2) {
                                var cube = new THREE.Mesh(new THREE.CubeGeometry(1, 1, 1), new THREE
                                    .MeshBasicMaterial({
                                        color: 0xC0C0C0
                                    }));
                                let x = ws * j + ws / 2;
                                let z = ws * i + ws / 2;
                                cube.position.set(x, 1.2, z);
                                scene.add(cube);
                            }
                        }
                        graph.push(nodeRow);
                    }

                }
            }

            //计算路径
            function caculatePath(resultArray) {
                var maps = new Graph(graph); // 地图
                var startX = parseInt(resultArray[0].position.z / ws);
                var startY = parseInt(resultArray[0].position.x / ws);
                var endX = parseInt(resultArray[1].position.z / ws);
                var endY = parseInt(resultArray[1].position.x / ws);
                var start = maps.grid[startX][startY];
                var end = maps.grid[endX][endY];
                result = astar.search(maps, start, end);
                if (result.length == 0) {
                    alert("无可到达路径");
                    cleanSphere();
                    return;
                }

                var nArr = [{
                    x: resultArray[0].position.x,
                    z: resultArray[0].position.z,
                    y: 1.2
                }];
                for (var i = 0; i < result.length; i++) {
                    let d = {
                        x: result[i].y * ws + ws / 2,
                        y: 1.2,
                        z: result[i].x * ws + ws / 2,
                    }
                    nArr.push(d);
                }
                initLine(nArr);
            }

            //清除小球
            function cleanSphere() {
                let child = scene.children; //获取场景中的所有子对象
                for (var i = 0; i < child.length; i++) {
                    if (child[i].geometry instanceof THREE.SphereGeometry) { //几何对象是球体几何
                        scene.remove(child[i]); //从场景中移除
                        i--;
                    }
                }
                isCaculate = false;
            }

            //初始球体
            function initSphere(x, z) {
                if (isCaculate) {
                    cleanSphere();
                }
                var geometry = new THREE.SphereGeometry(ws / 2, 30, 30); //球体几何
                var material = new THREE.MeshBasicMaterial({
                    color: 0xffff00
                }); //网格基础材料

                if (resultArray.length == 0) {
                    var sphere = new THREE.Mesh(geometry, material);
                    sphere.position.x = x;
                    sphere.position.y = 1;
                    sphere.position.z = z;
                    resultArray.push(sphere);
                    scene.add(sphere);
                } else if (resultArray[0].position.x != x || resultArray[0].position.z != z) {
                    var sphere = new THREE.Mesh(geometry, material);
                    sphere.position.x = x;
                    sphere.position.y = 1;
                    sphere.position.z = z;
                    resultArray.push(sphere);
                    scene.add(sphere);
                    caculatePath(resultArray);
                    isCaculate = true;
                    resultArray = new Array();
                }
            }

            // 绘制障碍物
            function initObstacles(x, z) {
                var name = "mesh_" + x + z;
                var obj = scene.getObjectByName(name);
                if (obj) {
                    scene.remove(obj);
                    for (var i = 0; i < meshArr.length; i++) {
                        if (meshArr[i].name == name) {
                            meshArr.splice(i, 1);
                        }
                    }
                    graph[parseInt(z / ws)][parseInt(x / ws)] = 1;
                } else {
                    var geometry = new THREE.BoxGeometry(ws, ws, ws); //球体几何
                    var material = new THREE.MeshBasicMaterial({
                        color: 0xff0000
                    });

                    var sphere = new THREE.Mesh(geometry, material);
                    sphere.position.x = x;
                    sphere.position.y = 1;
                    sphere.position.z = z;
                    sphere.name = name;
                    scene.add(sphere);
                    meshArr.push({
                        name: name,
                        obj: sphere,
                        x: x,
                        y: z,
                    });
                    graph[parseInt(z / ws)][parseInt(x / ws)] = 0;
                }
            }

            // 拾取对象
            function pickupObjects(event) {
                // 点击屏幕创建一个向量
                var raycaster = new THREE.Raycaster();
                var vector = new THREE.Vector2((event.clientX / window.innerWidth) * 2 - 1, -(event.clientY / window
                    .innerHeight) * 2 + 1);
                var fxl = new THREE.Vector3(0, 1, 0);
                var groundplane = new THREE.Plane(fxl, 0);
                raycaster.setFromCamera(vector, camera);
                var ray = raycaster.ray;
                let intersects = ray.intersectPlane(groundplane);
                let x = intersects.x;
                let z = intersects.z;

                if (x < 0 || z < 0 || length < z || length < x) {
                    return;
                }

                var k, m;
                for (var i = 0; i < length; i += ws) {
                    if (x >= i && x < i + ws) {
                        k = i + ws / 2;
                    }
                }
                for (var j = 0; j < length; j += ws) {
                    if (z >= j && z < j + ws) {
                        m = j + ws / 2;
                    }
                }


                if (controls.clickBool) {
                    initSphere(k, m); //初始化球体
                } else {
                    initObstacles(k, m);
                }
            }
            document.addEventListener('click', pickupObjects, false); //监听单击拾取对象初始化球体

            // 动画渲染
            var step = 5;

            function renderScene() {
                TWEEN.update();
                var delta = clock.getDelta();

                orbit.update();
                mixer.update(delta);

                // 使用requestAnimationFrame函数进行渲染
                requestAnimationFrame(renderScene);
                renderer.render(scene, camera);
            }

            // 渲染的场景
            renderer.render(scene, camera);

            // 创建一个球形几何体
            function createSphereGeometryLambertMaterial(point) {
                // 创建一个球体
                var sphereGeometry = new THREE.SphereGeometry(0.2, 20, 20);
                var sphereMaterial = new THREE.MeshBasicMaterial({
                    color: 0x7777ff,
                    wireframe: true
                });
                var sphereMaterial = new THREE.MeshLambertMaterial({
                    color: 0xff0000
                });
                var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
                // 设置该物体投射阴影
                sphere.castShadow = true;

                // 位置范围
                sphere.position.x = point.x;
                sphere.position.y = point.y;
                sphere.position.z = point.z;
                return sphere;
            }
        }
        window.onload = init;

        function onResize() {
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
            renderer.setSize(window.innerWidth, window.innerHeight);
        }
        // 监听调整大小事件
        window.addEventListener('resize', onResize, false);
    </script>
</body>

</html>